/**
 * Copyright (C) 2012 Dmitriy Kukharev
 *  
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package ru.nsu.weather.net;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import ru.nsu.weather.data.Weather;
import android.util.Xml;

public class WeatherParser {

	private static final String ns = null;
	   
    public Weather parse(InputStream in) throws XmlPullParserException, IOException {
        try {
            XmlPullParser parser = Xml.newPullParser();
            parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
            parser.setInput(in, null);
            parser.nextTag();
            return readWeather(parser);
        } finally {
            in.close();
        }
    }
    
    private Weather readWeather(XmlPullParser parser) throws XmlPullParserException, IOException {

    	Weather weather = new Weather();
        parser.require(XmlPullParser.START_TAG, ns, "weather");
        
        String startTimestamp = parser.getAttributeValue(null, "start_timestamp");
        String stopTimestamp = parser.getAttributeValue(null, "stop_timestamp");
        
        weather.setStart(Long.parseLong(startTimestamp));
        weather.setStop(Long.parseLong(stopTimestamp));

        while (parser.next() != XmlPullParser.END_TAG) {
            if (parser.getEventType() != XmlPullParser.START_TAG) {
                continue;
            }
            
            String name = parser.getName();
            if (name.equals("average")) {
            	parser.require(XmlPullParser.START_TAG, ns, name);
            	String average = readText(parser);
            	weather.setAverage(Double.parseDouble(average));
            	parser.require(XmlPullParser.END_TAG, ns, name);
            } else if (name.equals("current")) {
            	parser.require(XmlPullParser.START_TAG, ns, name);
            	String current = readText(parser);
            	weather.setCurrent(Double.parseDouble(current));
            	parser.require(XmlPullParser.END_TAG, ns, name);
            } else if (name.equals("graph")) {
            	weather.setPoints(readGraph(parser));
            } else {
            	skip(parser);
            }
        }  
        return weather;
    }
    
    private List<Weather.Point> readGraph(XmlPullParser parser) throws IOException, XmlPullParserException {
    	List<Weather.Point> points = new ArrayList<Weather.Point>();
    	parser.require(XmlPullParser.START_TAG, ns, "graph");
    	while (parser.next() != XmlPullParser.END_TAG) {
    		if (parser.getEventType() != XmlPullParser.START_TAG) {
                continue;
            }
    		
    		points.add(readPoint(parser)); 
    	}
    	parser.require(XmlPullParser.END_TAG, ns, "graph");
    	return points;
    }
    
    private Weather.Point readPoint(XmlPullParser parser) throws IOException, XmlPullParserException {
    	Weather.Point point = new Weather.Point();
    	parser.require(XmlPullParser.START_TAG, ns, "temp");
    	String timestamp = parser.getAttributeValue(null, "timestamp");
    	point.setTimestamp(Long.parseLong(timestamp));
    	point.setTemp(Double.parseDouble(readText(parser)));
    	parser.require(XmlPullParser.END_TAG, ns, "temp");
    	return point;
    }
    
    private String readText(XmlPullParser parser) throws IOException, XmlPullParserException {
        String result = "";
        if (parser.next() == XmlPullParser.TEXT) {
            result = parser.getText();
            parser.nextTag();
        }
        return result;
    }
    
    private void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
        if (parser.getEventType() != XmlPullParser.START_TAG) {
            throw new IllegalStateException();
        }
      
        int depth = 1;
        while (depth != 0) {
            switch (parser.next()) {
            case XmlPullParser.END_TAG:
                depth--;
                break;
            case XmlPullParser.START_TAG:
                depth++;
                break;
            }
        }
     }

}
